# coding: utf-8
# @Author: ChuiZi
import os

from settings import *
from options.configs import FrameDataPath
from lib.common.achieveData import merge_dict, load_xls, formatDict
from lib.common.manageFile import findAllFileBySuffix


class LoadTestDatas:
    def __init__(self, dataType: str = testCaseType):
        """数据处理为:[[[项目级,模块级,功能点]{测试场景:用例数据,测试场景2:用力数据,……]……]

        :param dataType:测试用例的格式,根据框架根目录下settings内的testCaseType参数决定,默认为xls
        """
        self.testCaseData = []  # 保存处理好的测试用例数据
        self.dataType = dataType  # 测试数据类型
        self.fileAbsPath = os.path.join(FrameDataPath.pathTestCaseDirRoot, dataType)  # 根据设置的数据拼接的测试用例目录的绝对地址
        self.loadData = {
            "xls": loadingXls,
            "csv": loadingCsv,
            "yaml": loadingYaml,
        }  # 内部方法的映射

    def run(self):
        """
        :return: 处理好符合本框架使用的数据格式组成的列表
        """
        self.testCaseData.clear()  # 清空内存数据,避免数据污染
        try:
            test_case_path = findAllFileBySuffix(self.fileAbsPath, self.dataType)
        except FileNotFoundError:
            raise "请检查根目录下settings中testCaseType参数设定的用例文件类型是否与测试用例文件格式相同"
        for path in test_case_path:
            self.testCaseData.extend(self.loadData[self.dataType](path))  # 通过映射和根目录下settings文件内设定的测试用例格式读取数据
        return dataFormat(self.testCaseData)  # 返回处理好的数据组成的列表,符合本框架使用的数据格式


# <editor-fold desc="读取不同格式数据的方法">
def loadingXls(*args, **kwargs):
    return load_xls(*args, **kwargs)


def loadingCsv():
    print(f"读取格式数据")


def loadingYaml():
    print(f"读取格式数据")


# </editor-fold>
# <editor-fold desc="数据的专项处理">
def dataFormat(testCaseDatas):
    """将符合要求的数据进行处理,返回符合本框架使用的数据

    :param testCaseDatas: 需要的格式为[{用例编号:1,用例描述:这是用例数据1,……},{用例编号:2,用例描述:这是用例数据2,……}……],所有用例参数组成的列表
    :return: 列表的深度体现用例所属,一维列表:项目级,二维列表:模块级,三维列表:功能点,四维列表:具体场景,对应的值为
    """
    datas_list = []
    for index in range(len(testCaseDatas)):
        # 将数据通过json深层转换为dict格式数据,以便后续读取
        testCaseDatas[index] = formatDict(testCaseDatas[index])
        # 将数据按照用例标识单独规整,等待后续用例数据合并,规整的格式为{epic:{feature:{story:{descript:{用例数据},descript:{用例数据}}}}组成的列表
        mark = testCaseDatas[index][allureTap]  # 简化字符写法
        datas_list.append({
            mark.get(allureTapEpic): {
                mark.get(allureTapFeature): {
                    mark.get(allureTapStory): {
                        testCaseDatas[index].get(caseDescript):
                            testCaseDatas[index]
                    }
                }
            }
        })
    # 将测试用例数据列表的数据进行合并
    temp_data = {}
    for data in datas_list:
        temp_data = merge_dict(data, temp_data)
    # 将测试用例数据调整为本框架使用的格式,以列表的深度体现用例所属,一维列表:项目级,二维列表:模块级,三维列表:功能点,四维列表:具体场景
    return traverseDict(temp_data)


def traverseDict(dic, deep_count=None, mark_list=None, deep_limt=None, datas=None):
    """将符合要求的数据转换为本框架需要用到的数据格式

    :param dic: 字典格式的测试用例数据
    :param datas:
    :return:
    """
    if deep_count is None:
        deep_count = 0  # 层级深度计数器
        deep_limt = 3  # 需要钻取的层级深度
        mark_list = []  # 用例标签缓存
        datas = []  # 返回数据缓存
    for key in dic.keys():  # 遍历当前目录下所有数据
        mark_list.append(key)  # 将当前目录标签添加进入缓存
        if deep_count < deep_limt:  # 未进入底层,执行的逻辑
            deep_count += 1
            traverseDict(dic[key], deep_count, mark_list, deep_limt, datas)  # 继续深入底层
            deep_count -= 1  # 切换到同目录下其他文件层级计算器需要相应减少数值
        else:  # 到达底层,执行的逻辑
            mark_list.pop()  # 到达底层后不需要底层的标签
            temp_data = {}
            for case in dic:  # 遍历底层所有的测试场景数据,case:每一个测试场景的数据
                # <editor-fold desc="对每一个测试场景的数据进行校验,例如格式上的校验">
                if not (isinstance(dic[case][params], dict) or dic[case][params] == ""):  # 参数传递的格式不为字典或者不为空则报错
                    raise TypeError(f"{dic[case][caseDescript]}场景的入参:{params}格式异常,预期为字典,实际为:{type(dic[case][params])}")
                # </editor-fold>
                temp_data[case] = dic[case]  # 获取当前功能点下所有测试场景汇聚成一个字典
            datas.append([mark_list.copy(), temp_data])  # 数组是容器,只存储地址,要用copy获取数据
            return datas
        mark_list.pop()  # 切换到同目录下其他文件标签缓存需要相应变更
    return datas
    # </editor-fold>


# </editor-fold>

if __name__ == '__main__':
    from lib.baseParams import rootPath

    pathDataXls = os.path.join(rootPath, r"options\temp\测试用例模板数据Xls格式.xls")
    # print(load_xls(pathDataXls))  # 默认有8条用例数据
    # print(dataFormat(load_xls(pathDataXls)))
    # print(LoadTestDatas().run())
    LoadTestDatas().run()
